﻿using System;
using System.Configuration;
using System.IO;
using System.Web;
using GigaSite.Domain.Entities;
using GigaSite.Domain.Interfaces.Cache;
using GigaSite.Domain.Interfaces.Repositories;

namespace GigaSite.Domain.DAL.Repositories
{
    /// <summary>
    /// СУБД реализация репозитория изображений
    /// </summary>
    public class ImagesRepository: BaseRepository<Image>,IImagesRepository
    {
        /// <summary>
        /// Глобальный кеш строк для хранения преобразованных URI
        /// </summary>
        private IStringCache StringCache { get; set; }

        /// <summary>
        /// Стандартный конструктор
        /// </summary>
        /// <param name="dataContext">Контекст данных</param>
        /// <param name="stringCache">Глобальный кеш строк</param>
        public ImagesRepository(GigaDataContext dataContext, IStringCache stringCache) : base(dataContext)
        {
            StringCache = stringCache;
        }

        /// <summary>
        /// Загружает указанную сущность по ее идентификатору
        /// </summary>
        /// <param name="id">Идентификатор сущности</param>
        /// <returns>Сущность с указанным идентификатором или Null</returns>
        public override Image Load(long id)
        {
            return Find(i => i.Id == id);
        }

        /// <remarks>Данный метод дважды вызывает SubmitChanges так что нужно использовать его с осторожностью</remarks>
        /// <summary>
        /// Сохраняет указанное изображение в сервером хранилище изображений
        /// </summary>
        /// <param name="postedFile"></param>
        /// <returns></returns>
        public Image SavePostedFile(HttpPostedFileBase postedFile)
        {
            // ФИзически сохраняем файл на сервере
            var imagesPath = ConfigurationManager.AppSettings["ImagesPath"];
            var serverFilename = string.Format("{0}{1}",Path.GetRandomFileName(),Path.GetExtension(postedFile.FileName));
            var fullPath = Path.Combine(imagesPath, serverFilename);
            postedFile.SaveAs(fullPath);

            //  Сохраняем информацию о файле в БД
            var image = new Image()
                            {
                                ContentSize = postedFile.InputStream.Length,
                                DateCreated = DateTime.Now,
                                MimeType = postedFile.ContentType,
                                OriginalFilename = postedFile.FileName,
                                ServerFilename = serverFilename,
                                Views = 0
                            };
            Add(image);

            // Добавляем в БД и строим URL
            SubmitChanges();
            image.BuildURI();
            SubmitChanges();

            // Отдаем результат
            return image;
        }

        /// <summary>
        /// Получает полный URL изображения по его URI в системе хранения файлов
        /// </summary>
        /// <param name="imageURI">URI файла в системе хранения контента</param>
        /// <returns>Полный путь к файлу на сервере</returns>
        public string GetFullImageURL(string imageURI)
        {
            // Пытаемся извлечь объект из кеша
            string alreadyParsed;
            bool hasInCache = false;
            if (StringCache.TryGetFromCache(imageURI, out alreadyParsed))
            {
                hasInCache = true;
                return alreadyParsed;
            }
            else
            {
                hasInCache = false;
            }
            
            var serverImageFolderPath = ConfigurationManager.AppSettings["ImageDBFolder"];
            // Загружаем используя более ранний метод
            var image = GetImage(imageURI);
            if (image == null)
            {
                return "/404.png";
            }
            
            // вычисляем путь
            //image.LastViewed = DateTime.Now;
            //image.Views = image.Views + 1;
            var path = String.Format("/{0}/{1}", serverImageFolderPath, image.ServerFilename);

            // Кладем строку в кеш
            if (!hasInCache)
            {
                StringCache.Set(imageURI,path);
            }

            // Отдаем картинку
            return path;
        }

        /// <summary>
        /// получает объект и данные по изображению
        /// </summary>
        /// <param name="imageURI">URI файла в системе хранения контента</param>
        /// <returns>Объект файла на сервере</returns>
        public Image GetImage(string imageURI)
        {
            // Парсим строку и вырываем из нее идентификатор
            var parts = imageURI.Split(new[] {"/"}, StringSplitOptions.RemoveEmptyEntries);
            var id = Convert.ToInt64(parts[2]);

            // Отдаем найденный если нашли
            return Load(id);
        }

        /// <summary>
        /// Удаляет сущность из репозитория
        /// </summary>
        /// <param name="entity">Сущность для удаления</param>
        public override void Delete(Image entity)
        {
            // Удаляем файл изображения с диска
            var imagesPath = ConfigurationManager.AppSettings["ImagesPath"];
            var path = Path.Combine(imagesPath, entity.ServerFilename);
            if (File.Exists(path))
            {
                try
                {
                    File.Delete(path);
                }
                catch (Exception e)
                {
                    // TODO: Log file deleting fails
                }
            }
            base.Delete(entity);
        }
    }
}